package com.base.kit;

import android.content.Context;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.base.kit.gson.TypeBuilder;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GsonUtil {
    private static final Gson gson = new Gson();

    /**
     * @param pClass   最外层的父类
     * @param objClass 父类里面的范型
     */
    @SuppressWarnings("rawtypes")
    public static
    @Nullable
    <Obj> PatternBean<Obj> json2Object(String json, Class<? extends PatternBean> pClass, Class<Obj> objClass) {
        try {
            Type type = TypeBuilder
                    .newInstance(pClass)
                    .addTypeParam(objClass)
                    .build();
            return gson.fromJson(json, type);
        } catch (RuntimeException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * {@link #json2Object(String, Class, Class)}
     *
     * @param pClass   最外层的父类
     * @param objClass 父类里面的范型
     */
    @SuppressWarnings("rawtypes")
    public static @Nullable
    <Obj> PatternBean<List<Obj>> json2Array(String json, Class<? extends PatternBean> pClass, Class<Obj> objClass) {
        try {
            Type type = TypeBuilder
                    .newInstance(pClass)
                    .beginSubType(List.class)
                    .addTypeParam(objClass)
                    .endSubType()
                    .build();
            return gson.fromJson(json, type);
        } catch (RuntimeException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static @Nullable
    <T> T json2Bean(String json, Class<T> tClass) {
        try {
            return gson.fromJson(json, tClass);
        } catch (RuntimeException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static @NonNull
    <T> List<T> json2List(String json, Class<T> tClass) {
        List<T> list = new ArrayList<>();
        if (TextUtils.isEmpty(json)) {
            return list;
        }
        try {
            JsonArray array = JsonParser.parseString(json).getAsJsonArray();
            for (JsonElement elem : array) {
                list.add(gson.fromJson(elem, tClass));
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return list;
        }
    }

    public static @NonNull
    String obj2Json(Object object) {
        try {
            if (null == object)
                return "{}";
            return gson.toJson(object);
        } catch (Exception e) {
            e.printStackTrace();
            return "{}";
        }
    }

    public static @NonNull
    String list2Json(Object object) {
        try {
            if (null == object)
                return "[]";
            return gson.toJson(object);
        } catch (Exception e) {
            return "[]";
        }
    }

    /**
     * @param context Context
     * @param resName json文件路径
     * @param tClass  要转换的类
     * @return List json文件转List
     */
    public static @NonNull
    <T> List<T> jsonFile2List(Context context, String resName, Class<T> tClass) {
        if (TextUtils.isEmpty(resName))
            return new ArrayList<>();
        String json = ResUtil.assetFile2String(context, resName);
        return json2List(json, tClass);
    }

    public static @Nullable
    <T> T jsonFile2Bean(Context context, String resName, Class<T> tClass) {
        if (TextUtils.isEmpty(resName))
            return null;
        String json = ResUtil.assetFile2String(context, resName);
        return TextUtils.isEmpty(json) ? null : json2Bean(json, tClass);
    }

    /**
     * @param isFile true：json格式的文件名
     *               false：标准的json格式字符串
     * @param json   isFile=true 如："test.json";
     *               isFile=false 如：{"name":"张三"};
     */
    public static @NonNull
    <T> List<T> json2List(Context context, String json, Class<T> t, boolean isFile) {
        List<T> list = new ArrayList<>();
        if (TextUtils.isEmpty(json)) {
            return list;
        }
        if (isFile)
            list = jsonFile2List(context, json, t);
        else
            list = json2List(json, t);
        return list;
    }

    public static <T> Map<String, T> json2Map(String result) {
        Map<String, T> map = new HashMap<>();
        if (TextUtils.isEmpty(result))
            return map;
        try {
            map = gson.fromJson(result, new TypeToken<HashMap<String, T>>() {
            }.getType());
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        return map;
    }
}